//Name: Sara Thorup
#include "dominion.h"
#include "dominion_helpers.h"
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "rngs.h"
#include <stdlib.h>
#include <time.h>

/*
Random tester for the adventurer card.  According to the dominion rules, playing the adventuerer card pulls the first two coin cards from the player's deck.
If a coin card is not found in the deck, shuffle the discard pile (do not put in the cards recently revealed) and continue drawing.
If 1 or none coin cards are found after this process - too bad.  The coin cards go into the player's hand. The revealed card are then discarded.

Things to randomize:
- # cards in deck
- # cards in discard
- # coin cards in deck and discard
*/

int getNumCoins(int maxCoins);
void testAdventurer();
int getDeckCount(int maxDeckCount);
int getDiscardCount(int maxDiscardCount);
void initalizeDecks(struct gameState* gameState, int playerNumber, int deckCount, int discardCount, int numCoins, int defaultCoin);
void insertCoinsIntoDecks(struct gameState* gameState, int playerNumber, int deckCount, int discardCount, int numCoins, int defaultCoin);
int getCoinsInDiscard(struct gameState* gameState, int playerNumber, int discardCount, int defaultCoin);
int getCoinsInDeck(struct gameState* gameState, int playerNumber, int deckCount, int defaultCoin);
void displayTestConditions(int numCoins, int deckCount, int discardCount, int coinsInDeck, int coinsInDiscard);
int getCoinsInHand(struct gameState* gameState, int playerNumber, int defaultCoin);

int main(int argc, char *argv[]) {
	srand(time(NULL));
	int numTestRuns = 10000;
	//printf("How many tests would you like to run? \n");
	//printf("Enter an integer: \n");  
	//scanf ("%d", &numTestRuns);
	printf("Attempting %d test runs. \n", numTestRuns);

	int i = 0;
	for (; i < numTestRuns; i++) {
		printf("\nRun # %d \n", i);
		testAdventurer();
	}
	
	return 0;
}

void testAdventurer() {
	int numPlayers = 2;
	int currentPlayer = 0;
	int maxDeckCount = 30;
	int maxDiscardCount = 30;
	int defaultCoin = gold;
	int kingdomCards[10] = {adventurer, council_room, feast, gardens, mine, remodel, smithy, village, baron, great_hall}; 
	int choice1 = 0;
	int choice2 = 0;
	int choice3 = 0;
	int bonus = 0;
	struct gameState* gameState = newGame();
	int randomSeed = 100;
	if (initializeGame(numPlayers, kingdomCards, randomSeed, gameState) != 0){
		printf("Error initalizing game. \n");
		printf("Number of players = %d \n", numPlayers);
		return;
	}


	//Set deck and card counts
	
	int deckCount = gameState->deckCount[currentPlayer] = getDeckCount(maxDeckCount);
	int discardCount = gameState->discardCount[currentPlayer] = getDiscardCount(maxDiscardCount);
	int maxCoins = deckCount + discardCount;
	int numCoins = getNumCoins(maxCoins);
	gameState->supplyCount[defaultCoin] = numCoins;

	//Fill player decks
	initalizeDecks(gameState, currentPlayer, deckCount, discardCount, numCoins, defaultCoin);
	
	int coinsInDeck = getCoinsInDeck(gameState, currentPlayer, deckCount, defaultCoin);
	int coinsInDiscard = getCoinsInDiscard(gameState, currentPlayer, discardCount, defaultCoin);

	displayTestConditions(numCoins, deckCount, discardCount, coinsInDeck, coinsInDiscard);

	//Tests
	int startHandCount = gameState->handCount[currentPlayer];
	cardEffect(adventurer, choice1, choice2, choice3, gameState, 0, &bonus);
	int newHandCount = gameState->handCount[currentPlayer];


	//If there are no coins, then there should be no coins in the player's hand. Handcount stays the same (minus played adventurer card)
	if (numCoins == 0) {
		if (getCoinsInHand(gameState, currentPlayer, defaultCoin) != 0) {
			printf("Error: There were no coins in the discard or deck piles.  No coins should be in the player's hand\n ");
		}
		if (startHandCount - 1 != newHandCount) {
			printf("Error: Handcount was incorrectly adjusted: Expected: %d, actual: %d\n", startHandCount-1, newHandCount);
		}
	}
	//If there was 1 coin, then there should be one coin in the player's hand. Handcount increases by one (minus played adventuer card);
	else if (numCoins == 1) {
		if (getCoinsInHand(gameState, currentPlayer, defaultCoin) != 1) {
			printf("Error: There was no coin in the player's hand even though one was in the player's deck or discard pile.\n ");
		}
		if (startHandCount != newHandCount) {
			printf("Error: Handcount was incorrectly adjusted: Expected: %d, actual: %d\n", startHandCount, newHandCount);
		}
	}
	//If there were 2 > coins, then there should be two coins in the player's hand
	else if (numCoins >= 2) {
		if (getCoinsInHand(gameState, currentPlayer, defaultCoin) != 2) {
			printf("Error: Expected 2 coins in hand.  %d coins were actually in the hand\n", getCoinsInHand(gameState, currentPlayer, defaultCoin));
		}
		if (startHandCount + 1 != newHandCount) {
			printf("Error: Handcount was incorrectly adjusted: Expected: %d, actual: %d\n", startHandCount + 1, newHandCount);
		}
	}
}

void displayTestConditions(int numCoins, int deckCount, int discardCount, int coinsInDeck, int coinsInDiscard) {
	printf("Test initialized with %d coins \n", numCoins);
	printf("The player's deck had %d cards\n", deckCount);
	printf("The player's discard pile had %d \n", discardCount);
	printf("%d coins were in the player's deck \n", coinsInDeck);
	printf("%d coins were in the player's discard pile \n", coinsInDiscard);

	printf("\n");

}

int getCoinsInDeck(struct gameState* gameState, int playerNumber, int deckCount, int defaultCoin) {
	int i = 0;
	int coinsInDeck = 0;
	for (; i < deckCount; i++) {
		if (gameState->deck[playerNumber][i] == defaultCoin) {
			coinsInDeck++;
		}
	}

	return coinsInDeck;
}

int getCoinsInDiscard(struct gameState* gameState, int playerNumber, int discardCount, int defaultCoin) {
	int i = 0;
	int coinsInDiscard = 0;
	for (; i < discardCount; i++) {
		if (gameState->discard[playerNumber][i] == defaultCoin) {
			coinsInDiscard++;
		}
	}

	return coinsInDiscard;
}

int getCoinsInHand(struct gameState* gameState, int playerNumber, int defaultCoin) {
	int handCount = gameState->handCount[playerNumber];
	int i = 0;
	int coinCount = 0;
	for ( ; i < handCount; i++) {
		if (gameState->hand[playerNumber][i] == defaultCoin) {
			coinCount++;
		}
	}

	return coinCount;
}

int getNumCoins(int maxCoins) {
	return rand() % (maxCoins + 1);
}

int getDeckCount(int maxDeckCount) {
	return rand() % (maxDeckCount + 1);
}

int getDiscardCount(int maxDiscardCount) {
	return rand() % (maxDiscardCount + 1);
}

void initalizeDecks(struct gameState* gameState, int playerNumber, int deckCount, int discardCount, int numCoins, int defaultCoin) {
	int defaultCard = estate;

	//setup hand to only hold the adventurer card. 
	gameState->handCount[playerNumber] = 1;
	gameState->hand[playerNumber][0] = adventurer;

	//setup deck
	gameState->deckCount[playerNumber] = deckCount;
	int cardNumber = 0;
	for ( ; cardNumber < deckCount; cardNumber++) {
		gameState->deck[playerNumber][cardNumber] = defaultCard;
	}

	//setup discard pile
	gameState->discardCount[playerNumber] = discardCount;
	cardNumber = 0;
	for ( ; cardNumber < discardCount; cardNumber++) {
		gameState->discard[playerNumber][cardNumber] = estate;
	}

	//insert coins randomally into decks
	insertCoinsIntoDecks(gameState, playerNumber, deckCount, discardCount, numCoins, defaultCoin);
}

void insertCoinsIntoDecks(struct gameState* gameState, int playerNumber, int deckCount, int discardCount, int numCoins, int defaultCoin) {
	int coinsRemaining = numCoins;
	int deckOrDiscard= 0;  //deck = 0, discard = 1
	int position = 0;
	//Inserts coins into the existing discard and deck decks.  Randomally chooses whether coin should be inserted in discard or deck.
	//Randomally picks position to insert card.
	while (coinsRemaining > 0) {
		deckOrDiscard = rand() % 2;
		if (deckOrDiscard == 0) {
			if (deckCount != 0) {
				position = rand() % deckCount;
				if (gameState->deck[playerNumber][position] != gold) {
					gameState->deck[playerNumber][position] = gold;
					coinsRemaining--;
				}
			}
		} else if (deckOrDiscard == 1) {
			if (discardCount != 0) {
				position = rand() % discardCount;
				if (gameState->discard[playerNumber][position] != gold) {
					gameState->discard[playerNumber][position] = gold;
					coinsRemaining--;
				}
			}
		} else {
			printf("Error deciding where to place coin \n");
		}
	}
}

